/*
 * The contents of this file are subject to the Mozilla Public License
 * Version 1.1 (the "License"); you may not use this file except in
 * compliance with the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS"
 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
 * License for the specific language governing rights and limitations
 * under the License.
 * 
 * The Original Code is iSQL-Viewer, A Mutli-Platform Database Tool.
 *
 * The Initial Developer of the Original Code is iSQL-Viewer, A Mutli-Platform Database Tool.
 * Portions created by Mark A. Kobold are Copyright (C) 2000-2007. All Rights Reserved.
 *
 * Contributor(s): 
 *  Mark A. Kobold [mkobold <at> isqlviewer <dot> com].
 *  
 * If you didn't download this code from the following link, you should check
 * if you aren't using an obsolete version: http://www.isqlviewer.com
 */
package org.isqlviewer.ui.wizards.service;

import java.awt.Component;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Enumeration;

import javax.swing.Box;
import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFileChooser;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JToolBar;

import org.isqlviewer.sql.ConnectionProfile;
import org.isqlviewer.sql.JdbcService;
import org.isqlviewer.swing.SwingUtilities;
import org.isqlviewer.ui.renderer.FileListCellRenderer;
import org.isqlviewer.ui.wizards.AbstractWizardStep;
import org.isqlviewer.ui.wizards.WizardContext;
import org.isqlviewer.util.LocalMessages;

public class ConfigureServiceResources extends AbstractWizardStep implements ActionListener {

    private LocalMessages messages = new LocalMessages(ServiceWizard.BUNDLE_NAME);
    private DefaultListModel fileListModel = new DefaultListModel();
    private JList fileList = new JList(fileListModel);
    private static final int ACTION_ADD_FILE = 0;
    private static final int ACTION_REMOVE_FILE = 1;

    public void actionPerformed(ActionEvent event) {

        String command = event.getActionCommand();
        Component source = (Component) event.getSource();
        int action = -1;
        try {
            action = Integer.parseInt(command);
        } catch (Exception error) {
            error.printStackTrace();
        }
        switch (action) {
            case ACTION_REMOVE_FILE :
                int[] idxs = fileList.getSelectedIndices();
                for (int i = idxs.length - 1; i >= 0; i--) {
                    fileListModel.removeElementAt(idxs[i]);
                }
                break;
            case ACTION_ADD_FILE :
                File[] f = SwingUtilities.getSystemFiles(source, JFileChooser.FILES_AND_DIRECTORIES);
                if (f != null) {
                    for (int i = 0; i < f.length; i++) {
                        fileListModel.addElement(f[i]);
                    }
                }
                break;
            default :
                break;
        }
    }

    public boolean isFirst() {

        return false;
    }

    public boolean isLast() {

        return false;
    }

    public boolean isValid(WizardContext context) {

        JdbcService service = (JdbcService) context.getAttribute(ServiceWizard.ATTRIBUTE_SERVICE);
        ArrayList<URL> classPath = new ArrayList<URL>();
        int count = fileListModel.getSize();
        for (int i = 0; i < count; i++) {
            File file = (File) fileListModel.get(i);
            try {
                classPath.add(file.toURL());
            } catch (MalformedURLException e) {
                context.error("file.toURL()", e);
            }
        }

        URLClassLoader classLoader = new URLClassLoader(classPath.toArray(new URL[count]));
        ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
        Thread.currentThread().setContextClassLoader(classLoader);
        try {
            Class.forName(service.getDriverClass(), false, classLoader);
        } catch (ClassNotFoundException error) {
            String localMessage = messages.format("newservicewizard.class-not-found", service.getDriverClass());
            context.showErrorDialog(null, localMessage);
            return false;
        } catch (Error error) {
            String localMessage = messages.format("newservicewizard.class-init-error", service.getDriverClass());
            context.showErrorDialog(null, localMessage);
            return false;
        } finally {
            Thread.currentThread().setContextClassLoader(contextClassLoader);
            classLoader = null;
            System.gc();
        }

        ConnectionProfile profile = service.getProfile();
        if (profile != null) {
            Enumeration<File> existingElements = profile.resourceElements();
            while (existingElements.hasMoreElements()) {
                profile.removeResource(existingElements.nextElement());
            }
        } else {
            profile = new ConnectionProfile();
            service.setProfile(profile);
        }
        for (int i = 0; i < count; i++) {
            profile.addResource((File) fileListModel.get(i));
        }
        return true;
    }

    @Override
    public void init(WizardContext context) {

        setTitle(messages.getMessage("newservicewizard.configure-resources.title"));
        setComment(messages.getMessage("newservicewizard.configure-resources.tip"));
        setImage(SwingUtilities.loadIconResource(ServiceWizard.class, "database", 22));

        GridBagConstraints constraint = null;
        String tip = null;

        JPanel panel = new JPanel(new GridBagLayout());
        setView(panel);

        JComponent component = new JToolBar(JToolBar.VERTICAL);
        ((JToolBar) component).setFloatable(false);
        constraint = ServiceWizard.constrain(0, 0, 1, 1, 0.0, 1.0, GridBagConstraints.NORTHWEST,
                GridBagConstraints.NONE);
        panel.add(component, constraint);

        tip = messages.format("newservicewizard.jdbcurlexample.tip");
        fileList.setToolTipText(tip);
        fileList.setCellRenderer(new FileListCellRenderer());
        // fileList.setDropTarget(null);
        constraint = ServiceWizard.constrain(1, 0, 1, 1, 1.0, 1.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH);
        panel.add(new JScrollPane(fileList), constraint);

        JButton actionButton = null;

        actionButton = new JButton(SwingUtilities.loadIconResource(ServiceWizard.class, "add", 16));
        actionButton.addActionListener(this);
        actionButton.setActionCommand(Integer.toString(ACTION_ADD_FILE));
        actionButton.setToolTipText(messages.getMessage("newservicewizard.add-resources.tip"));
        component.add(actionButton);

        actionButton = new JButton(SwingUtilities.loadIconResource(ServiceWizard.class, "delete", 16));
        actionButton.addActionListener(this);
        actionButton.setActionCommand(Integer.toString(ACTION_REMOVE_FILE));
        actionButton.setToolTipText(messages.getMessage("newservicewizard.delete-resources.tip"));
        component.add(actionButton);

        component = (JComponent) Box.createVerticalGlue();
        component.setName("GLUE");
        component.setToolTipText(tip);
        constraint = ServiceWizard.constrain(0, 7, 2, 1, 0.0, 1.0, GridBagConstraints.CENTER,
                GridBagConstraints.VERTICAL);
        panel.add(component, constraint);
    }

    @Override
    public void activate(WizardContext context) {

        super.activate(context);
        JdbcService service = (JdbcService) context.getAttribute(ServiceWizard.ATTRIBUTE_SERVICE);
        if (fileListModel.isEmpty()) {
            ConnectionProfile profile = service.getProfile();
            Enumeration<File> files = profile.resourceElements();
            while (files.hasMoreElements()) {
                fileListModel.addElement(files.nextElement());
            }
        }
    }
}